package coint.btc.util;

import java.io.UnsupportedEncodingException;
import java.math.BigDecimal;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.text.DecimalFormat;
import java.text.NumberFormat;
import java.text.ParseException;
import java.util.Arrays;
import java.util.UUID;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.apache.commons.lang3.StringUtils;
import org.apache.poi.ss.formula.functions.T;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import lombok.extern.log4j.Log4j;

/**
 * 通用工具类
 * @author BOOM
 *
 */
@Log4j
public class CommonUtil {
	
	
	private static Logger   log = LoggerFactory.getLogger(CommonUtil.class);

    /**
     * 对信息进行MD5加密
     * 
     * @param msg
     *            要被加密的信息
     * @return 加密后的信息
     */
    public static String encrypt(String msg) {
        return encryptWithSalt(msg, null);
    }

    /**
     * 对信息进行MD5加密, 同时加盐防止破解
     * 
     * @param msg
     *            要被加密的信息
     * @return 加密后的信息
     */
    public static String encryptWithSalt(String msg, CharSequence salt) {
        if (salt != null) {
            msg += salt;
        }
        MessageDigest md5 = null;
        try {
            md5 = MessageDigest.getInstance("MD5");
        } catch (NoSuchAlgorithmException e) {
            log.error("加密算法不存在", e);
            return null;
        }
        try {
            md5.update(msg.getBytes("UTF-8"));
        } catch (UnsupportedEncodingException e) {
            log.error("加密失败", e);
            return null;
        }
        byte[] buf = md5.digest();
        StringBuffer sb = new StringBuffer();
        for (int i = 0; i < buf.length; i++) {
            if (Integer.toHexString(0xff & buf[i]).length() == 1) {
            	sb.append("0").append(Integer.toHexString(0xff & buf[i]));
            } else {
            	sb.append(Integer.toHexString(0xff & buf[i]));
            }
        }
        return sb.toString();
    }

    /**
     * 生成32为UUID
     * @return
     */
    public static String get32UUID() {
        return UUID.randomUUID().toString().trim().replaceAll("-", "");
    }
    
    /**
     * 判断多个数字之间互等
     * @param num n个数字
     * @return  任意两个相等返回true
     * @author  Zc
     * @since   2017年5月13日 上午11:19:31
     */
    public static boolean existEquals(Number... num) {
        int length = num.length;
        if (length < 2) {
            return false;
        }
        BigDecimal hero = new BigDecimal(num[0].toString());
        for (int i = 1; i < length; ++i) {
            if (num[i] == null) {
                return false;
            } else if (compareNumber(hero, num[i]) == 0) {
                return true;
            }
        }
        return existEquals(Arrays.copyOfRange(num, 1, length));
    }

    /**
    * 判断多个数字之间互不相等
    * @param num n个数字
    * @return  任意两个数字相等返回false
    * @author  Zc
    * @since   2017年5月13日 上午11:34:17
    */
    public static boolean nonEquals(Number... num) {
        return !existEquals(num);
    }

    /**
     * 精确比较两个任意数字
     * @param num1 被比较数
     * @param num2 比较数
     * @return  1代表num1大于num2, 0代表相等, -1代表小于
     * @author  Zc
     * @since   2017年5月27日 上午10:08:15
     */
    public static int compareNumber(Number num1, Number num2) {
        return new BigDecimal(num1.toString()).compareTo(new BigDecimal(num2.toString()));
    }

    /**
     * 对数字数组进行指定范围的升序排序
     * @param arr   数字数组
     * @param left  起始索引
     * @param right 结束索引
     * @author  Zc
     * @since   2017年5月28日 下午12:31:39
     */
    public static void ascSortNumArr(Number[] arr, int left, int right) {
        if (left > right) {
            return;
        }
        int i = left, j = right;
        Number start = arr[left], temp = null;
        while (i < j) {
            while (i < j && compareNumber(start, arr[j]) <= 0) {
                --j;
            }
            while (i < j && compareNumber(start, arr[i]) >= 0) {
                ++i;
            }
            if (i < j) {
                temp = arr[i];
                arr[i] = arr[j];
                arr[j] = temp;
                temp = null;
            }
        }
        arr[left] = arr[i];
        arr[i] = start;
        ascSortNumArr(arr, left, i - 1);
        ascSortNumArr(arr, i + 1, right);
    }

    /**
     * 对数字数组进行全范围升序排序
     * @param arr   数组
     * @author  Zc
     * @since   2017年5月28日 下午12:31:02
     */
    public static void ascSortNumArr(Number[] arr) {
        ascSortNumArr(arr, 0, arr.length - 1);
    }

    /**
     * 根据Unicode编码判断是否为中文
     * @param c 单字符
     * @return  是中文返回true
     * @author  Zc
     * @since   2017年5月9日 上午10:32:34
     */
    public static boolean isChinese(char c) {
        Character.UnicodeBlock ub = Character.UnicodeBlock.of(c);
        if (ub == Character.UnicodeBlock.CJK_UNIFIED_IDEOGRAPHS
                || ub == Character.UnicodeBlock.CJK_COMPATIBILITY_IDEOGRAPHS
                || ub == Character.UnicodeBlock.CJK_UNIFIED_IDEOGRAPHS_EXTENSION_A
                || ub == Character.UnicodeBlock.CJK_UNIFIED_IDEOGRAPHS_EXTENSION_B
                || ub == Character.UnicodeBlock.CJK_SYMBOLS_AND_PUNCTUATION
                || ub == Character.UnicodeBlock.HALFWIDTH_AND_FULLWIDTH_FORMS
                || ub == Character.UnicodeBlock.GENERAL_PUNCTUATION) {
            return true;
        }
        return false;
    }

    /**
     * 首字母转换为大写
     * @param str 要被转换的字符串
     * @return  转换后的字符串
     * @author  Zc
     * @since   2017年5月15日 下午3:16:08
     */
    public static String initcap(String str) {
        if (!StringUtils.isEmpty(str)) {
            char[] ch = str.toCharArray();
            if (ch[0] >= 'a' && ch[0] <= 'z') {
                ch[0] = (char) (ch[0] - 32);
            }
            return new String(ch);
        }
        return str;
    }

    /**
     * 返回String类型数据
     * @param obj 要被转化的对象
     * @return  为null返回null
     * @author  Zc
     * @since   2017年5月18日 下午11:55:57
     */
    public static String parseString(Object obj) {
        if (obj != null) {
            return obj.toString();
        }
        return null;
    }

    /**
     * 处理数字字符串, 加上num后以length为补零返回
     * @param str       数字字符串
     * @param num       被加数
     * @param length    总长度
     * @return  处理好的数字字符串
     * @author  Zc
     * @since   2017年5月22日 下午4:44:12
     */
    public static String processNumStr(String str, Integer num, Integer length) {
        Integer strNum = Integer.valueOf(str);
        strNum += num;
        return fillNumString(strNum.toString(), length);
    }

    /**
     * 将指定数字字符串补零处理
     * @param num       数字字符串
     * @param length    补零总长度
     * @return  补零后的字符串
     * @author  Zc
     * @since   2017年5月22日 下午4:45:17
     */
    public static String fillNumString(String num, Integer length) {
        if ((num + "").length() >= length) {
            return num.toString();
        }
        return fillNumString("0" + num, length);
    }

    /**
     * 对传入的数字进行精度处理，保留两位小数
     * @param   num 要被处理的数字
     * @return  小数点两位的数字
     * @author  Zc
     * @since   2017年5月6日 上午10:21:43
     */
    public static String scaleMoney(Number num) {
        if (num == null) {
            return "";
        }
        DecimalFormat df = new DecimalFormat("0.00");
        return df.format(num);
    }

    /**
     * 对传入的数字进行精度处理，保留两位小数
     * @param str 要被处理的字符串
     * @return  小数点两位的数字
     * @author  Zc
     * @since   2017年5月6日 上午10:51:43
     */
    public static String scaleMoney(String str) {
        if (StringUtils.isBlank(str)) {
            return "";
        }
        Number num = null;
        try {
            num = NumberFormat.getInstance().parse(str);
        } catch (ParseException e) {
            return null;
        }
        return scaleMoney(num);
    }

    /**
     * 将一个值封装进对应类型数组返回
     * @param   value   做
     * @return  数组
     * @author  Zc
     * @since   2017年8月3日 下午4:29:10
     */
    public static T[] getArrWith(T value) {
        T[] arr = new T[] { value };
        return arr;
    }

    /**
    * 精确计算多个数字相减的封装方法
    * @param minuend       被减数
    * @param subtrahends   减数
    * @return              精准的计算结果
    * @record      2017年4月5日 下午5:55:27 Zc创建
    */
    public static Number preciseSubstract(Number minuend, Number... subtrahends) {
        BigDecimal result = new BigDecimal(String.valueOf(minuend.doubleValue()));
        for (Number subtrahend : subtrahends) {
            if (subtrahend == null) {
                continue;
            }
            result = result.subtract(new BigDecimal(String.valueOf(subtrahend.doubleValue())));
        }
        return result;
    }

    /**
    * 精确计算多个数字相乘的封装方法
    * @param numbers   数字数组
    * @return          精准的计算结果
    * @record      2017年4月2日 上午9:24:01 Zc创建
    */
    public static Number preciseMultiply(Number... numbers) {
        BigDecimal result = new BigDecimal("1");
        for (Number number : numbers) {
            if (number == null) {
                continue;
            }
            result = result.multiply(new BigDecimal(String.valueOf(number.doubleValue())));
        }
        return result;
    }
    
    
	/**
	 * @Description:四舍五入
	 * @author:wf
	 * @time:2017年11月2日 下午2:18:05
	 * @param xiaoshuwei保留小数位数
	 * @param num要四舍五入的数
	 * @return
	 */
	public static double sishewuru(Integer xiaoshuwei,Double num){
		if(null != num){
			BigDecimal b = new BigDecimal(num);  
			double rel =  b.setScale(xiaoshuwei,BigDecimal.ROUND_HALF_UP).doubleValue();
			return rel;
		}
		return 0.00;
	}
	
	/**
	 * @Description:去掉时间后的毫秒数
	 * @author:wf
	 * @time:2017年11月24日 上午10:47:47
	 * @param oldTime
	 * @return
	 */
	public static String subformat(String oldTime){
		if(StringUtils.isNotEmpty(oldTime) && oldTime.contains(".")){
			return  oldTime.substring(0, oldTime.indexOf("."));
		}else{
			return  oldTime ;
		}
	}
	
	/**
	* @Description 将字符串中的emoji表情转换成可以在utf-8字符集数据库中保存的格式（表情占4个字节，需要utf8mb4字符集）
	* @param str
	* 待转换字符串
	* @return 转换后字符串
	* @throws UnsupportedEncodingException
	* exception
	*/
	public static String emojiConvert1(String str) throws UnsupportedEncodingException {
		String patternString = "([\\x{10000}-\\x{10ffff}\ud800-\udfff])";
	
		Pattern pattern = Pattern.compile(patternString);
		Matcher matcher = pattern.matcher(str);
		StringBuffer sb = new StringBuffer();
		while(matcher.find()) {
		try {
		matcher.appendReplacement(
		sb,
		"[["
		+ URLEncoder.encode(matcher.group(1),
		"UTF-8") + "]]");
		} catch(UnsupportedEncodingException e) {
		throw e;
		}
		}
		matcher.appendTail(sb);
		return sb.toString();
	}

	/**
	* @Description 还原utf8数据库中保存的含转换后emoji表情的字符串
	* @param str
	* 转换后的字符串
	* @return 转换前的字符串
	* @throws UnsupportedEncodingException
	* exception
	*/
	public static String emojiRecovery2(String str) throws UnsupportedEncodingException {
		String patternString = "\\[\\[(.*?)\\]\\]";
	
		Pattern pattern = Pattern.compile(patternString);
		Matcher matcher = pattern.matcher(str);
	
		StringBuffer sb = new StringBuffer();
		while(matcher.find()) {
		try {
		matcher.appendReplacement(sb,
		URLDecoder.decode(matcher.group(1), "UTF-8"));
		} catch(UnsupportedEncodingException e) {
		throw e;
		}
		}
		matcher.appendTail(sb);
		return sb.toString();
	}
}